import api from "@/http/api";

export const loadOptions = (mode, tabSize) => {
  return {
    mode: mode || 'javascript',
    theme: 'dracula',
    lineNumbers: true,
    lineWrapping: true,
    smartIndent: true,
    indentUnit: tabSize ? tabSize : 2,
    matchBrackets: true,
    showCursorWhenSelecting: true,
    autoRefresh: true,
    tabSize: tabSize ? tabSize : 2,
    foldGutter: true,
    gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
    styleActiveLine: true,
    keyMap: "sublime",
    matchTags: { bothTags: true },
    styleSelectedText: true,
    highlightDifferences: true,
    highlightSelectionMatches: {
      minChars: 2,
      trim: true,
      style: 'match-highlight',
      showToken: false
    },
    extraKeys: {
      Tab: (cm) => {
        if (cm.somethingSelected()) {
          cm.indentSelection('add');
        } else {
          cm.replaceSelection(Array(cm.getOption("indentUnit") + 1).join(" "), "end", "+input");
        }
      }
    }
  }
};

export const loadModelHint = async() => {
  const resultList = [];
  const res = await api.post("/system/dataModel/queryList");
  res.data && res.data.forEach(item => {
    resultList.push("模型：" + item.name + " " + item.code);
  });
  return resultList;
};

export const loadGroovyHint = async() => {
  const resultList = [];
  const res = await api.post("/system/scriptGroovy/queryList");
  res.data && res.data.forEach(item => {
    resultList.push("脚本：" + item.name + " " + item.id);
  });
  return resultList;
};

export const loadDictionaryHint = async() => {
  const resultList = [];
  const res = await api.post("/system/dictionary/queryList");
  res.data && res.data.forEach(item => {
    resultList.push("字典：" + item.name + " " + item.id);
  });
  return resultList;
};

export const showHint = (instance, hintList) => {
  const cursor = instance.getCursor();
  const curLine = instance.getLine(cursor.line);
  const chWord = /[\u4e00-\u9fa5]+/;
  const word = /[\u4e00-\u9fa5\w]+/;
  let end = cursor.ch, start = end;
  while (start && word.test(curLine.charAt(start - 1))) --start;
  let curWord = start !== end && curLine.slice(start, end);
  if (!curWord || curWord.length < 2) {
    return;
  }

  curWord = curWord.toLowerCase();
  const found = [];
  function maybeAdd(str) {
    if (str.toLowerCase().indexOf(curWord) >= 0 && !arrayContains(found, str))
      found.push(str);
  }
  forEach(hintList, maybeAdd);

  function arrayContains(arr, item) {
    if (!Array.prototype.indexOf) {
      let i = arr.length;
      while (i--) {
        if (arr[i] === item) {
          return true;
        }
      }
      return false;
    }
    return arr.indexOf(item) !== -1;
  }

  function forEach(arr, f) {
    for (let i = 0, e = arr.length; i < e; ++i) f(arr[i]);
  }

  const words = new Set([...found, /*...anyhint.list, ...jshint.list*/]);
  if(words.size > 0) {
    const wordList = [];
    words.forEach(word => {
      const displayText = word;
      const text = word.startsWith("模型：") || word.startsWith("脚本：") || word.startsWith("字典：")
        ? word.substr(word.lastIndexOf(" ") + 1) : word
      wordList.push({displayText: displayText, text: text});
    });
    instance.showHint({
      completeSingle: false,
      completeOnSingleClick: true,
      closeCharacters: /[\s()\[\]{};:>,'"]/,
      closeOnPick: true,
      hint: (cm) => {
        const cursor = cm.getCursor();
        const curLine = instance.getLine(cursor.line);

        let start = cursor.ch;
        while (start && (curLine.charAt(start - 1) === '.' || word.test(curLine.charAt(start - 1)))) {
          if (chWord.test(curLine.charAt(start - 1))) {
            start = start - 2;
          } else {
            start--;
          }
        }

        return {
          list: wordList,
          from: { ch: start, line: cursor.line },
          to: { ch: cursor.ch, line: cursor.line },
        };
      },
    });
  } else {
    instance.closeHint();
  }
};

export default {
  loadOptions,
  loadModelHint,
  loadGroovyHint,
  loadDictionaryHint,
  showHint
};